//
//  CLVCMain.m
//  CLBrowser
//
//  Created by 梁慧聪 on 2021/7/12.
//

#import <StoreKit/StoreKit.h>

#import "CLVCMain.h"
#import "CLWebTopBar.h"

#import "CLWebBottomBar.h"
#import "CLCardMainView.h"
#import "CLVCSetting.h"
#import "CLVCSettingTable.h"
#import "CLVCHistory.h"
#import "CLDelegateManager+WebViewDelegate.h"
#import "CLVCBookmark.h"
#import "CLBookmarkDataManager.h"
#import "CLVCBookmarkEdit.h"
#import "CLFindInPageBar.h"
#import "CLKeyboardHelper.h"
#import "NSURL+CLUtility.h"
#import "CLVCExtentions.h"

static NSString *const kCLVCBrowserAddBookmarkSuccess = @"添加书签成功";
static NSString *const kCLVCBrowserAddBookmarkFailure = @"添加书签失败";

@interface CLVCMain ()<CLWebBottomBarClickDelegate, UIViewControllerRestoration, CLKeyboardHelperDelegate>

@property (nonatomic, strong) CLWebBottomBar *webBottomBar;
@property (nonatomic, strong) CLWebTopBar *webTopToolBar;
@property (nonatomic, assign) CGFloat lastContentOffset;
@property (nonatomic, assign) BOOL isWebViewDecelerate;
@property (nonatomic, assign) CLScrollDirection webViewCLScrollDirection;
@property (nonatomic, weak) id<CLWebBottomBarClickDelegate> webBottomBarDelegate;
@property (nonatomic, strong) CLFindInPageBar *findInPageBar;
@property (nonatomic, weak) NSLayoutConstraint *findInPageBarbottomLayoutConstaint;

@end
@implementation CLVCMain

SYNTHESIZE_SINGLETON_FOR_CLASS(CLVCMain);

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self initializeView];
    
    [self initializeNotification];

    self.lastContentOffset = - TOP_TOOL_BAR_HEIGHT;
    
    [[CLDelegateManager sharedInstance] registerDelegate:self forKeys:@[kDelegateManagerWebView, kDelegateManagerFindInPageBarDelegate]];
    [[CLKeyboardHelper sharedInstance] addDelegate:self];
    
    self.restorationIdentifier = NSStringFromClass([self class]);
    self.restorationClass = [self class];
}

- (void)initializeView {
    
    UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];
    [self.navigationItem setBackBarButtonItem:backItem];
    
    self.webContainerView = ({
        CLWebContainerView *webContainerView = [[CLWebContainerView alloc] initWithFrame:CGRectMake(0, 0, self.contentView.width, self.contentView.height)];
        [self.contentView addSubview:webContainerView];
        self.webBottomBarDelegate = webContainerView;
        webContainerView;
    });
    
    self.webTopToolBar = ({
        CGFloat yOrigin = 0;
        if ([CLUtility isIphoneX]) {
            yOrigin = 24;
            UIView *gapView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.contentView.width, yOrigin)];
            gapView.backgroundColor = UIColorFromRGB(0xF8F8F8);
            [self.contentView addSubview:gapView];
        }
        
        CLWebTopBar *browserTopToolBar = [[CLWebTopBar alloc] initWithFrame:CGRectMake(0, yOrigin, self.contentView.width, TOP_TOOL_BAR_HEIGHT)];
        [self.contentView addSubview:browserTopToolBar];
        
        browserTopToolBar;
    });
    
    self.webBottomBar = ({
        CLWebBottomBar *toolBar = [[CLWebBottomBar alloc] initWithFrame:CGRectMake(0, self.contentView.height - BOTTOM_TOOL_BAR_HEIGHT, self.contentView.width, BOTTOM_TOOL_BAR_HEIGHT)];
        [self.contentView addSubview:toolBar];
        
        toolBar.browserButtonDelegate = self;
        
        [self.webContainerView addObserver:toolBar forKeyPath:@"webView" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:NULL];
    
        toolBar;
    });
}

#pragma mark - Notification

- (void)initializeNotification{
    [Notifier addObserver:self selector:@selector(recoverToolBar) name:kExpandHomeToolBarNotification object:nil];
    [Notifier addObserver:self selector:@selector(recoverToolBar) name:kWebTabSwitch object:nil];
}

#pragma mark - UIScrollViewDelegate Method

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //点击新链接或返回时，scrollView会调用该方法
    if (!(!scrollView.decelerating && !scrollView.dragging && !scrollView.tracking)) {
        CGFloat yOffset = scrollView.contentOffset.y - self.lastContentOffset;
        
        if (self.lastContentOffset > scrollView.contentOffset.y) {
            if (_isWebViewDecelerate || (scrollView.contentOffset.y >= -TOP_TOOL_BAR_HEIGHT && scrollView.contentOffset.y <= 0)) {
                //浮点数不能做精确匹配，不过此处用等于满足我的需求
                if (!(self.webTopToolBar.height == TOP_TOOL_BAR_HEIGHT)) {
                    [self recoverToolBar];
                }
            }
            self.webViewCLScrollDirection = CLScrollDirectionDown;
        }
        else if (self.lastContentOffset < scrollView.contentOffset.y && scrollView.contentOffset.y >= - TOP_TOOL_BAR_HEIGHT)
        {
            if (!(scrollView.contentOffset.y < 0 && scrollView.decelerating)) {
                [self handleToolBarWithOffset:yOffset];
            }
            self.webViewCLScrollDirection = CLScrollDirectionUp;
        }
    }
    
    self.lastContentOffset = scrollView.contentOffset.y;
    
}

- (void)recoverToolBar {
    [UIView animateWithDuration:.2 animations:^{
        self.webTopToolBar.height = TOP_TOOL_BAR_HEIGHT;
        CGRect bottomRect = self.webBottomBar.frame;
        bottomRect.origin.y = self.contentView.height - BOTTOM_TOOL_BAR_HEIGHT;
        self.webBottomBar.frame = bottomRect;
        self.webContainerView.scrollView.contentInset = UIEdgeInsetsMake(TOP_TOOL_BAR_HEIGHT, 0, BOTTOM_TOOL_BAR_HEIGHT, 0);
    }];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    if (self.webViewCLScrollDirection == CLScrollDirectionDown) {
        self.isWebViewDecelerate = decelerate;
    }
    else
        self.isWebViewDecelerate = NO;
}

#pragma mark - Handle TopToolBar Scroll

- (void)handleToolBarWithOffset:(CGFloat)offset {
    if (self.webBottomBar.hidden || self.webTopToolBar.hidden) {
        return;
    }
    CGRect bottomRect = self.webBottomBar.frame;
    //缩小toolbar
    if (offset > 0) {
        if (self.webTopToolBar.height - offset <= TOP_TOOL_BAR_THRESHOLD) {
            self.webTopToolBar.height = TOP_TOOL_BAR_THRESHOLD;
            self.webContainerView.scrollView.contentInset = UIEdgeInsetsMake(TOP_TOOL_BAR_THRESHOLD, 0, 0, 0);

            bottomRect.origin.y = self.contentView.height;
        }
        else {
            self.webTopToolBar.height -= offset;
            CGFloat bottomRectYoffset = BOTTOM_TOOL_BAR_HEIGHT * offset / (TOP_TOOL_BAR_HEIGHT - TOP_TOOL_BAR_THRESHOLD);
            bottomRect.origin.y += bottomRectYoffset;
            UIEdgeInsets insets = self.webContainerView.scrollView.contentInset;
            insets.top -= offset;
            insets.bottom -= bottomRectYoffset;
            self.webContainerView.scrollView.contentInset = insets;
        }
    }
    else {
        if (self.webTopToolBar.height + (-offset) >= TOP_TOOL_BAR_HEIGHT) {
            self.webTopToolBar.height = TOP_TOOL_BAR_HEIGHT;
            bottomRect.origin.y = self.contentView.height - BOTTOM_TOOL_BAR_HEIGHT;
            self.webContainerView.scrollView.contentInset = UIEdgeInsetsMake(TOP_TOOL_BAR_HEIGHT, 0, BOTTOM_TOOL_BAR_HEIGHT, 0);
        }
        else {
            self.webTopToolBar.height += (-offset);
            CGFloat bottomRectYoffset = BOTTOM_TOOL_BAR_HEIGHT * (-offset) / (TOP_TOOL_BAR_HEIGHT - TOP_TOOL_BAR_THRESHOLD);
            bottomRect.origin.y -= bottomRectYoffset;
            UIEdgeInsets insets = self.webContainerView.scrollView.contentInset;
            insets.top += (-offset);
            insets.bottom += bottomRectYoffset;
            self.webContainerView.scrollView.contentInset = insets;
        }
    }
    
    self.webBottomBar.frame = bottomRect;
}

#pragma mark - CLWebBottomBarClickDelegate

- (void)browserBottomToolBarButtonClickedWithTag:(CLBottomToolBarTag)tag {
    WEAK_SELF;
    if ([self.webBottomBarDelegate respondsToSelector:@selector(browserBottomToolBarButtonClickedWithTag:)]) {
        [self.webBottomBarDelegate browserBottomToolBarButtonClickedWithTag:tag];
    }
    switch (tag) {
        case CLBottomToolBarTagMore:
        {
            WEAK_SELF;
            UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
            
            [alertController addAction:[UIAlertAction actionWithTitle:@"扩展" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                CLVCExtentions *vc = [[CLVCExtentions alloc] initWithStyle:UITableViewStyleGrouped];
                [CLNavigationService pushController:vc animated:YES];
            }]];
            [alertController addAction:[UIAlertAction actionWithTitle:@"加入书签" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                [weakSelf addBookmark];
            }]];
            [alertController addAction:[UIAlertAction actionWithTitle:@"书签" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                CLVCBookmark *vc = [[CLVCBookmark alloc] initWithStyle:UITableViewStylePlain];
                [CLNavigationService pushController:vc animated:YES];
            }]];
            [alertController addAction:[UIAlertAction actionWithTitle:@"历史" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                CLVCHistory *vc = [[CLVCHistory alloc] initWithStyle:UITableViewStylePlain];
                [CLNavigationService pushController:vc animated:YES];
            }]];
            [alertController addAction:[UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                CLVCSettingTable *vc = [[CLVCSettingTable alloc] initWithStyle:UITableViewStylePlain];
                [CLNavigationService pushController:vc animated:YES];
            }]];
            [alertController addAction:[UIAlertAction actionWithTitle:@"拷贝连接" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                [weakSelf handleCopyURLButtonClicked];
            }]];
            [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
            
            //显示弹窗视图控制器
            [self presentViewController:alertController animated:YES completion:nil];
            
        }
            break;
        case CLBottomToolBarTagMultiWindow:
        {
            CLCardMainView *cardMainView = [[CLCardMainView alloc] initWithFrame:self.contentView.bounds];
            [cardMainView reloadCardMainViewWithCompletionBlock:^{
                UIImage *image = [weakSelf.contentView snapshot];
                UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
                imageView.frame = cardMainView.bounds;
                [cardMainView addSubview:imageView];
                [weakSelf.contentView addSubview:cardMainView];
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [imageView removeFromSuperview];
                    [cardMainView changeCollectionViewLayout];
                });
            }];
        }
            break;
        default:
            break;
    }
}

- (void)handleCopyURLButtonClicked {
    NSURL *url = [NSURL URLWithString:self.webContainerView.webView.mainFURL];
    BOOL success = NO;
    
    if (url) {
        if ([url isErrorPageURL]) {
            url = [url originalURLFromErrorURL];
        }
        UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];
        pasteBoard.URL = url;
        success = YES;
    }

    [self.contentView showHUDWithMessage:success ? @"拷贝成功" : @"拷贝失败"];
}

- (void)addBookmark {
    CLWebView *webView = self.webContainerView.webView;
    NSString *title = webView.mainFTitle;
    NSString *url = webView.mainFURL;
    
    if (title.length == 0 || url.length == 0) {
        [self.contentView showHUDWithMessage:kCLVCBrowserAddBookmarkFailure];
        return;
    }
    CLBookmarkDataManager *dataManager = [[CLBookmarkDataManager alloc] init];
    CLVCBookmarkEdit *editVC = [[CLVCBookmarkEdit alloc] initWithDataManager:dataManager item:[BookmarkItemModel bookmarkItemWithTitle:title url:url] sectionIndex:[NSIndexPath indexPathForRow:0 inSection:0] operationKind:BookmarkItemOperationKindItemAdd completion:nil];
    [CLNavigationService pushController:editVC animated:YES];
}

#pragma mark - Preseving and Restoring State

+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder {
    return CLMainVC;
}

#pragma mark - CLFindInPageBarDelegate

- (void)findInPage:(CLFindInPageBar *)findInPage didFindPreviousWithText:(NSString *)text {
    [self.findInPageBar endEditing:YES];
}

- (void)findInPage:(CLFindInPageBar *)findInPage didFindNextWithText:(NSString *)text {
    [self.findInPageBar endEditing:YES];
}

- (void)findInPageDidPressClose:(CLFindInPageBar *)findInPage {
    [self updateFindInPageVisibility:NO];
}

- (void)updateFindInPageVisibility:(BOOL)visible {
    if (visible) {
        if (!self.findInPageBar) {
            CLFindInPageBar *findInPageBar = [CLFindInPageBar new];
            findInPageBar.translatesAutoresizingMaskIntoConstraints = NO;
            [self.contentView addSubview:findInPageBar];
            
            [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[findInPageBar]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(findInPageBar)]];
            [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[findInPageBar(44)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(findInPageBar)]];
            NSLayoutConstraint *bottomConstaint = [NSLayoutConstraint constraintWithItem:findInPageBar attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_webBottomBar attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.f];
            [self.contentView addConstraint:bottomConstaint];
            self.findInPageBarbottomLayoutConstaint = bottomConstaint;
            
            self.findInPageBar = findInPageBar;
        }
    }
    else if (self.findInPageBar) {
        [self.findInPageBar endEditing:YES];
        [self.findInPageBar removeFromSuperview];
        self.findInPageBar = nil;
    }
}

#pragma mark - FindInPageUpdateDelegate

- (void)findInPageDidUpdateCurrentResult:(NSInteger)currentResult {
    self.findInPageBar.currentResult = currentResult;
}

- (void)findInPageDidUpdateTotalResults:(NSInteger)totalResults {
    self.findInPageBar.totalResults = totalResults;
}

- (void)findInPageDidSelectForSelection:(NSString *)selection {
    [self updateFindInPageVisibility:YES];
    self.findInPageBar.text = selection;
}

#pragma mark - CLKeyboardHelperDelegate

- (void)keyboardHelper:(CLKeyboardHelper *)keyboardHelper keyboardWillShowWithState:(CLKeyboardState *)state {
    [self changeSearchInputViewPoint:state isShow:YES];
}

- (void)keyboardHelper:(CLKeyboardHelper *)keyboardHelper keyboardWillHideWithState:(CLKeyboardState *)state {
    [self changeSearchInputViewPoint:state isShow:NO];
}

- (void)changeSearchInputViewPoint:(CLKeyboardState *)state isShow:(BOOL)isShow {
    if (!(self.navigationController.topViewController == self && !self.presentedViewController && self.findInPageBar)) {
        return;
    }
    
    CGFloat keyBoardEndY = self.contentView.height - [state intersectionHeightForView:self.contentView];
    
    // 添加移动动画，使视图跟随键盘移动
    [UIView animateWithDuration:state.animationDuration animations:^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationCurve:state.animationCurve];
#pragma clang diagnostic pop
        [self.findInPageBarbottomLayoutConstaint setActive:NO];
        if (isShow) {
            NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.findInPageBar attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0f constant:keyBoardEndY];
            self.findInPageBarbottomLayoutConstaint = bottomConstraint;
            [self.contentView addConstraint:bottomConstraint];
        }
        else{
            NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.findInPageBar attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.webBottomBar attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.f];
            self.findInPageBarbottomLayoutConstaint = bottomConstraint;
            [self.contentView addConstraint:bottomConstraint];
        }
    }];
}

- (void)startLoadWebViewWithURL:(NSString *)url {
    [self.webContainerView startLoadWebViewWithURL:url];
}

#pragma mark - Dealloc Method

- (void)dealloc {
    [Notifier removeObserver:self];
}

- (BOOL)isHiddenNaviBar {
    return YES;
}
@end
